﻿/* ****************************************************************************
* Copyright (c) TCC - 2009 IME - USP. 
*
* This source code is subject to terms and conditions of the Microsoft Public License. 
* A copy of the license can be found in http://msdn.microsoft.com/en-us/library/dd228915.aspx. 
* By using this source code in any fashion, you are agreeing to be bound by the terms of the 
* Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
* ***************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace SoundLibrary.Converter
{
    public class OBuffer
    {
        public const int OBUFFERSIZE = 2 * 1152;
        public const int MAXCHANNELS = 2;

        static readonly int CHANNELS = 2;
        int _offset;
        int _end;
        byte[] buffer = new byte[OBUFFERSIZE * 2];
        int[] bufferp = new int[MAXCHANNELS];

        #region Contructor

        public OBuffer()
        {
            clear_buffer();
        }

        #endregion

        #region Public Methods

        public int bytesLeft
        {
            get { return _end - _offset; }
        }

        public int Read(byte[] buffer_out, int offset, int count)
        {
            int remaining = bytesLeft;
            int copySize;
            if (count > remaining)
            {
                copySize = remaining;
                Debug.Assert(copySize % (2 * CHANNELS) == 0);
            }
            else
            {
                int remainder = count % (2 * CHANNELS);
                copySize = count - remainder;
            }

            Array.Copy(buffer, _offset, buffer_out, offset, copySize);

            _offset += copySize;
            return copySize;
        }

        #endregion

        #region Obuffer Override

        public void append(int channel, short value)
        {
            buffer[bufferp[channel]] = (byte)(value & 0xff);
            buffer[bufferp[channel] + 1] = (byte)(value >> 8);
            bufferp[channel] += CHANNELS * 2;
        }

        public void appendSamples(int channel, float[] f)
        {
            int pos = bufferp[channel];

            float fs;
            for (int i = 0; i < 32; i++)
            {
                fs = f[i];
                if (fs > 32767.0f)
                    fs = 32767.0f;
                else if (fs < -32767.0f)
                    fs = -32767.0f;

                int sample = (int)fs;
                buffer[pos] = (byte)(sample & 0xff);
                buffer[pos + 1] = (byte)(sample >> 8);

                pos += CHANNELS * 2;
            }

            bufferp[channel] = pos;
        }

        public void clear_buffer()
        {
            _offset = 0;
            _end = 0;

            for (int i = 0; i < CHANNELS; i++)
                bufferp[i] = i * 2;
        }

        public void set_stop_flag()
        {
        }

        public void write_buffer(int val)
        {
            _offset = 0;
            _end = bufferp[0];
        }

        public void close()
        {
        }

        #endregion
    }
}